//
//  main.m
//  OBJC_Message
//
//  Created by wangrui on 14-5-9.
//  Copyright (c) 2014年 PPS. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
#import "NSObject+DLIntrospection.h"
#import "TestIntrospectionClass.h"
#import "TestMessageSendClass.h"

void testIntrospection()
{
    NSLog(@"%@",[NSObject protocols]);//只有NSObject协议
    NSLog(@"NSObject Protocal :%@",[NSObject descriptionForProtocol:objc_getProtocol("NSObject")]);//输出NSObject协议的方法
    NSLog(@"%@",[NSObject instanceVariables]); //只有isa指针
    
    printf("\n====================================================================================\n\n");
    
    NSLog(@"TestIntrospectionClass classMethods:%@",[TestIntrospectionClass classMethods]);
    NSLog(@"TestIntrospectionClass instanceMethods:%@",[TestIntrospectionClass instanceMethods]);
    NSLog(@"TestIntrospectionClass instanceVariables:%@",[TestIntrospectionClass instanceVariables]);
    NSLog(@"TestIntrospectionClass protocols:%@",[TestIntrospectionClass protocols]);
    NSLog(@"TestIntrospectionClass properties:%@",[TestIntrospectionClass properties]);
    NSLog(@"TestIntrospectionClass parentClassHierarchy:%@",[TestIntrospectionClass parentClassHierarchy]);
}

void testMessageSend()
{
    TestMessageSendClass *tc = [TestMessageSendClass new];
    [tc testMethod];
    [tc testMethodWithArguments:@""];
    
    //先把 objc_msgSend 这个函数的类型转化为一个 "返回值是id，参数为id,sel" 的函数指针，再送入参数
    NSString *result = ((id (*)(id, SEL))objc_msgSend)(tc, @selector(objc_msgSendTest)); //效果一样
    NSLog(@"%@",result);
}

/*
 *use clang rewrite code.   ‘clang -rewrite-objc ./main.m’
 *
 *  void testMessageSend()
    {
        //类方法 先用objc_getClass找到元类(根据类的isa指针,找到类方法)
        TestMessageSendClass *tc = ((id (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("TestMessageSendClass"), sel_registerName("new"));
     
        //实例方法 直接根据对象的isa指针找到实例方法
        ((void (*)(id, SEL))(void *)objc_msgSend)((id)tc, sel_registerName("testMethod"));
     
        ((void (*)(id, SEL, id))(void *)objc_msgSend)((id)tc, sel_registerName("testMethodWithArguments:"), (id)(NSString *)&"constantStringAdress");
    }
 *
 */


int main(int argc, const char * argv[])
{

    @autoreleasepool {
        //testIntrospection();
        testMessageSend();
    }
    return 0;
}

